/******************************************************************************
 *  _____     _____
 *  \  __\    \  __\
 *   \ \_\\    \ \_\\
 *    \  __\SS  \  __\roject
 *     \_\       \_\
 *
 * Mateusz Maciąg, Rafał Urbański
 * Komputerowe Systemy Sterowania
 *****************************************************************************/

#include "WaveformBase.h"

#include "Utils.h"
#include <sstream>

// Przestrzeń nazw
namespace RafMat
{
namespace SimEngine
{

using namespace std;
using namespace SimInterface;

const string WaveformBase::CONF_TYPE = "type";
const string WaveformBase::CONF_GAIN = "gain";
const string WaveformBase::CONF_PERIOD = "period";
const string WaveformBase::CONF_OFFSET = "offset";
const string WaveformBase::CONF_PHASE = "phase";

WaveformBase::WaveformBase(SimInterface::ISimulator& simulator, string type,
             double gain, double period,
             double offset, double phase)
    : m_simulator(simulator),
      m_type(type),
      m_gain(gain), m_period(period),
      m_offset(offset), m_phase(phase)
{
}

WaveformBase::WaveformBase(SimInterface::ISimulator& simulator, std::string name,
             string type, double gain,
             double period, double offset, double phase)
    : IConfigurable(name),
      m_simulator(simulator),
      m_type(type),
      m_gain(gain), m_period(period),
      m_offset(offset), m_phase(phase)
{
}

bool WaveformBase::setParameter(const string& param, const string& value) throw(logic_error)
{
    // Usuń ewentualne wiodące i końcowe spacje
    string tparam = Utils::trimWhiteSpaces(param);
    string tvalue = Utils::trimWhiteSpaces(value);

    // Strumień danych dla łańcucha argumentu.
    istringstream istr(tvalue);

    double tmpVal;
    double *target;

    if(tparam == CONF_GAIN)
        target = &this->m_gain;
    else if(tparam == CONF_PERIOD)
        target = &this->m_period;
    else if(tparam == CONF_OFFSET)
        target = &this->m_offset;
    else if(tparam == CONF_PHASE)
        target = &this->m_phase;
    else
        throw iconf_error::unrecognizedParam(*this, tparam);

    istr >> tmpVal;
    if(!istr.bad())
    {
        *target = tmpVal;
    }
    else
    {
        throw iconf_error::syntaxError(*this, tvalue);
    }

    return true;
}

string WaveformBase::getParameter(const string& param) const throw(logic_error)
{
    // Usuń ewentualne wiodące i końcowe spacje
    string tparam = Utils::trimWhiteSpaces(param);
    string outStr;

    // Strumień danych dla łańcucha argumentu.
    ostringstream ostr(outStr);

    const double * target;

    if(tparam == CONF_TYPE)
    {
        ostr << m_type;
        return ostr.str();
    }
    else if(tparam == CONF_GAIN)
        target = &this->m_gain;
    else if(tparam == CONF_PERIOD)
        target = &this->m_period;
    else if(tparam == CONF_OFFSET)
        target = &this->m_offset;
    else if(tparam == CONF_PHASE)
        target = &this->m_phase;
    else
        throw iconf_error::unrecognizedParam(*this, tparam);

    ostr << *target;
    return ostr.str();
}

SimFile::ConfigWriter& WaveformBase::dumpParameters(SimFile::ConfigWriter& o) const
{
    o.pushBlock(SimFile::ConfigWriter::BlockInput, getName());
    o.pushParam(CONF_TYPE, m_type);
    this->dumpSpecificPar(o);
    o.closeBlock();
    return o;
}

SimFile::ConfigWriter& WaveformBase::dumpSpecificPar(SimFile::ConfigWriter& o) const
{
    o.pushParam(CONF_GAIN, m_gain);
    o.pushParam(CONF_PERIOD, m_period);
    o.pushParam(CONF_OFFSET, m_offset);
    o.pushParam(CONF_PHASE, m_phase);
    return o;
}

}   // SimEngine namespace
}   // RafMat namespace
